/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { type Dialog, type IpcMain } from 'electron'
import { promises as fs } from 'fs'
import path from 'path'
import configjson from '../../resources/airspace-slice/config.json?commonjs-external&asset'
import logger from 'electron-log'

/**
 * Open file selection dialog for user to select a file and get its path
 */
const openFileDialog = async (dialog: Dialog, ipcMain: IpcMain) => {
  // Handle file selection
  ipcMain.handle('window-select-geojson', async () => {
    try {
      const { canceled, filePaths } = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [
          {
            name: 'GeoJSON Files',
            extensions: ['geojson', 'json']
          },
          {
            name: 'All Files',
            extensions: ['*']
          }
        ]
      })
      if (canceled) {
        logger.info('User canceled file selection')
        return null
      }

      return filePaths[0]
    } catch (error) {
      logger.error('Error opening file selection dialog:', error)
      return null
    }
  })

  ipcMain.handle('window-select-tif', async () => {
    try {
      const { canceled, filePaths } = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [
          {
            name: 'GeoTIFF Files',
            extensions: ['tif', 'tiff']
          },
          {
            name: 'All Files',
            extensions: ['*']
          }
        ]
      })
      if (canceled) {
        logger.info('User canceled file selection')
        return null
      }

      return filePaths[0]
    } catch (error) {
      logger.error('Error opening file selection dialog:', error)
      return null
    }
  })
}

/**
 * Open directory selection dialog for user to select a folder and get its path
 * @param browserWindow Reference to the current window
 * @returns Selected directory path, or null if selection was canceled
 */
const openDirectoryDialog = async (dialog: Dialog, ipcMain: IpcMain) => {
  // Handle folder selection
  ipcMain.handle('window-select-folder', async () => {
    try {
      const { canceled, filePaths } = await dialog.showOpenDialog({
        properties: ['openDirectory']
      })
      if (canceled) {
        logger.info('User canceled folder selection')
        return null
      }

      return filePaths[0]
    } catch (error) {
      logger.error('Error opening folder selection dialog:', error)
      return null
    }
  })
}

/**
 * Read config.json configuration file
 * @param ipcMain Main process IPC object
 * @param configPath Configuration file path, uses default path if not provided
 */
const readConfigFile = async (ipcMain: IpcMain) => {
  // Default config file path
  const defaultConfigPath = configjson.replace('app.asar', 'app.asar.unpacked')

  // Register IPC handler
  ipcMain.handle('read-config-file', async (_, customPath?: string) => {
    try {
      const filePath = customPath || defaultConfigPath

      // Check if file exists
      try {
        await fs.access(filePath)
      } catch (error) {
        logger.error(`Config file does not exist or cannot be accessed: ${filePath}`, error)
        return null
      }
      // Read file content
      const fileContent = await fs.readFile(filePath, 'utf-8')
      const config = JSON.parse(fileContent)
      logger.info(`Successfully read config file: ${filePath}`)
      return config as unknown
    } catch (error) {
      logger.error('Error reading config file:', error)
      return null
    }
  })
}

/**
 * Write config.json configuration file
 * @param ipcMain Main process IPC object
 * @param configPath Configuration file path, uses default path if not provided
 */
const writeConfigFile = async (ipcMain: IpcMain) => {
  // Default config file path
  const defaultConfigPath = configjson.replace('app.asar', 'app.asar.unpacked')

  // Register IPC handler
  ipcMain.handle('write-config-file', async (_, config: unknown, customPath?: string) => {
    try {
      const filePath = customPath || defaultConfigPath

      // Ensure directory exists
      const dirPath = path.dirname(filePath)
      await fs.mkdir(dirPath, { recursive: true })

      // Write file content
      await fs.writeFile(filePath, JSON.stringify(config, null, 4), 'utf-8')
      logger.info(`Successfully wrote config file: ${filePath}`)
      return true
    } catch (error) {
      logger.error('Error writing config file:', error)
      return false
    }
  })
}

export { openFileDialog, openDirectoryDialog, readConfigFile, writeConfigFile }
